#ifndef ASSET_MANAGER_H
#define ASSET_MANAGER_H

#include "Asset.h"
#include "Singleton.h"
#include <map>
#include <memory>

namespace Engine
{
	class AssetManager : public NonCopyable
	{
		private:
			friend class Singleton <AssetManager>;
			AssetManager(){}

			std::map <std::string, std::shared_ptr <Asset>> m_assetMap;

		public:
			//to use type Engine::TheAssetManager::Instance() ->Get <type> ("filename");
			template <typename T>
			std::shared_ptr <T> Get(const std::string& name)
			{
				//see if asset already exists
				auto i = m_assetMap.find(name);

				//if it does return it
				if(i != m_assetMap.end())
					return std::dynamic_pointer_cast <T> (i ->second);

				//if it doesnt create a new asset
				std::shared_ptr <Asset> ptr(new T());

				//try to load the asset if unable to load return empty pointer
				if(!ptr ->Load(name))
					return std::shared_ptr <T> ();

				//if loaded add to asset map and return it
				m_assetMap[name] = (std::static_pointer_cast <T> (ptr));
				return std::dynamic_pointer_cast <T> (ptr);
			}

			template <typename T>
			std::shared_ptr <T> Get(rapidxml::xml_node <>* node)
			{
				if(!node ->first_node("FileName"))
				{
					return std::shared_ptr <T> ();
				}
				std::string name = node ->first_node("FileName") ->value();
				
				//see if asset already exists
				auto i = m_assetMap.find(name);

				//if it does return it
				if(i != m_assetMap.end())
					return std::dynamic_pointer_cast <T> (i ->second);

				//if it doesnt create a new asset
				std::shared_ptr <Asset> ptr(new T());

				//try to load the asset if unable to load return empty pointer
				if(!ptr ->Load(node))
					return std::shared_ptr <T> ();

				//if loaded add to asset map and return it
				m_assetMap[name] = (std::static_pointer_cast <T> (ptr));
				return std::dynamic_pointer_cast <T> (ptr);
			}

			bool Remove(const std::string& name)
			{
				auto it = m_assetMap.find(name);
				//remove if there are 2 (or less) ref counts remaining (the asset in map, and the one being used)
				if((it != m_assetMap.end()) && (it ->second.use_count() < 2))
					m_assetMap.erase(it);
			}

			void RemoveAll()
			{
				m_assetMap.clear();
			}
	};

	typedef Singleton <AssetManager> TheAssetManager;
}

#endif

